﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using AwesomeEnginePC.Physics;
using AwesomeEnginePC.Extras;

namespace AwesomeEnginePC.Graphics.TwoDimensional
{
    public abstract class Base2DObject : BaseGraphicalObject
    {
        /// <summary>
        /// The x-y position of the object
        /// </summary>
        public virtual Vector<int> Position { get; set; }
        /// <summary>
        /// The layer depth of the object.
        /// </summary>
        public virtual float LayerDepth { get; set; }

        /// <summary>
        /// A Point that describes the origin of the object. 
        /// Remember to use RawHeight and RawWidth instead of regular Height and Width; this value is calculated before any scaling is applied.
        /// </summary>
        public virtual Vector<int> Origin { get; set; }

        /// <summary>
        /// The rotation of the object, in Radians.
        /// </summary>
        public virtual float Rotation { get; set; }

        /// <summary>
        /// The scaling of the draw object on the X and Y axis.
        /// </summary>
        public virtual Vector<float> Scaling { get; set; }

        /// <summary>
        /// The Tint of the object, with default white. If object is a font, this property is the color of its text, with default black.
        /// </summary>
        public virtual Color Tint { get; set; }

        /// <summary>
        /// Gets the center point of the sprite (using raw values).
        /// </summary>
        public Vector<int> CenterPoint
        {
            get { return new Vector<int>(RawWidth / 2, RawHeight / 2); }
        }

        /// <summary>
        /// The drawn height of the object. Does take into consideration the object's scaling. If setting the value, changes the ScalingY value so the displayed height is the value.
        /// </summary>
        public int Height
        {
            get { return (int)(RawHeight * Scaling.Y); }
            set { Scaling.X = value * 1.0f / RawHeight; }
        }

        /// <summary>
        /// The drawn width of the object. Does take into consideration the object's scaling. If setting the value, changes the ScalingX value so the displayed width is the value.
        /// </summary>
        public int Width
        {
            get { return (int)(RawWidth * Scaling.X); }
            set { Scaling.X = value * 1.0f / RawWidth; }
        }

        /// <summary>
        /// The raw width of the object.
        /// </summary>
        public abstract int RawWidth { get; }

        /// <summary>
        /// The raw height of the object.
        /// </summary>
        public abstract int RawHeight { get; }

        public Base2DObjectSettings GetBase2DObjectSettings()
        {
            return new Base2DObjectSettings()
            {
                Position = this.Position,
                LayerDepth = this.LayerDepth,
                Origin = this.Origin,
                Rotation = this.Rotation,
                Scaling = this.Scaling,
                Tint = this.Tint,
            };
        }

        public void LoadFromSettings(Base2DObjectSettings settings)
        {
            Position = settings.Position;
            LayerDepth = settings.LayerDepth;
            Origin = settings.Origin;
            Rotation = settings.Rotation;
            Scaling = settings.Scaling;
            Tint = settings.Tint;
        }

        protected virtual void SetDefaultValues()
        {
            this.Position = new Vector<int>();
            this.Tint = Color.White;
            this.Rotation = 0f;
            this.Origin = new Vector<int>();
            this.LayerDepth = 0f;
            this.Scaling = new Vector<float>(1, 1);
        }

        public Base2DObject(ContentManager cm, bool setDefaultValues = true)
            : base(cm)
        {
            if (setDefaultValues)
                SetDefaultValues();
        }

        public virtual bool IsPointOnObject(Vector<int> point)
        {
            return (point.X.IsBetween(this.Position.X, this.Position.X + this.Width, true, true)) &&
                (point.Y.IsBetween(this.Position.Y, this.Position.Y + this.Height, true, true));
        }
    }
}
